In [1]:
from IPython.html import widgets
from IPython.display import display
from eventful_graph import EventfulGraph
from widget_forcedirectedgraph import ForceDirectedGraphWidget, publish_js
publish_js()


Prime Factor Finder

Find the prime numbers inside a large integer


In [2]:
def is_int(number):
    return int(number) == number

def factor_int(number):
    return [i + 1 for i in range(number) if is_int(number / (float(i) + 1.0))]

In [3]:
import time
BACKGROUND = '#F7EBD5'
PARENT_COLOR = '#66635D'
FACTOR_COLOR = '#6CC5C1'
EDGE_COLOR = '#000000'
PRIME_COLOR = '#E54140'

existing_graphs = []

def add_unique_node(graph, value, **kwargs):
    index = len(graph.node)
    graph.add_node(index, charge=-50, strokewidth=0, value=value, **kwargs)
    return index

def plot_primes(graph, number, parent, start_number, delay=0.0):
    if delay > 0.0:
        time.sleep(delay)
        
    factors = factor_int(number)
    if len(factors) > 2:
        for factor in factors:
            if factor != number and factor != 1 :
                factor_size = max(float(factor) / start_number * 30.0,3.0)
                parent_factor_size = max(float(number) / start_number * 30.0,3.0)
                index = add_unique_node(graph, number, fill=FACTOR_COLOR, r='%.2fpx' % factor_size)
                graph.add_edge(index, parent, distance=parent_factor_size+factor_size, stroke=EDGE_COLOR)
                plot_primes(graph, factor, parent=index, start_number=start_number, delay=delay)
    else:
        # Prime, set parent color to prime color.
        graph.node[parent]['fill'] = PRIME_COLOR

def graph_primes(number, delay):
    if len(existing_graphs) > 0:
        for graph in existing_graphs:
            graph.close()
        del existing_graphs[:]
        
    floating_container = widgets.PopupWidget()
    floating_container.description = "Factors of %d" % number
    floating_container.button_text = str(number)
    floating_container.set_css({
        'width': '620px',
        'height': '450px'}, selector='modal')
        
    graph = EventfulGraph()
    d3 = ForceDirectedGraphWidget(graph)
    floating_container.children = [d3]
    floating_container.set_css('background', BACKGROUND)
    d3.width = 600
    d3.height = 400
    display(floating_container)
    existing_graphs.append(floating_container)
    
    index = add_unique_node(graph, number, fill=PARENT_COLOR, r='30px')
    plot_primes(graph, number=number, parent=index, start_number=number, delay=delay)

In [4]:
box = widgets.ContainerWidget()
header = widgets.HTMLWidget(value="<h1>Number Factorizer</h1><br>")
subbox = widgets.ContainerWidget()
number = widgets.IntSliderWidget(value=100)
button = widgets.ButtonWidget(description="Calculate")
subbox.children = [number, button]
speed = widgets.FloatSliderWidget(min=0.0, max=0.5, value=0.4, step=0.01)
box.children = [header, subbox, speed]
display(box)

box.add_class('vbox')
box.add_class('align-center')
box.add_class('center')
subbox.add_class('hbox')
subbox.add_class('align-center')
subbox.add_class('center')
box.add_class('well well-small')

def handle_caclulate(sender):
    graph_primes(number.value, 0.5-speed.value)
button.on_click(handle_caclulate)